# Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com>
#
# This file is part of paramiko.
#
# Paramiko is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2.1 of the License, or (at your option)
# any later version.
#
# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.


import socket
import sys
from paramiko.py3compat import u

unsupport_cmd_list = ['rz', 'sz']

# windows does not have termios...
try:
    import termios
    import tty
    import time

    has_termios = True
except ImportError:
    has_termios = False


# interactive.interactive_shell(chan,main_ins,host_ip,username)
def interactive_shell(chan, main_ins, host_ip, username, host_ins):
    if has_termios:
        # print '--->posix:', main_ins.login_user,host_ip,username
        posix_shell(chan, main_ins, host_ip, username, host_ins)  # unix shell
    else:
        windows_shell(chan)


def posix_shell(chan, self, host_ip, username, host_ins):
    '''
    此种方式是肆意妄为2，就是当你触发一下键盘就会发送[支持tab 补全]，而不是肆意妄为1那种，只有敲击回车时候，才一行一行的发送数据,并不支持tab 补全。。
    '''
    import select
    oldtty = termios.tcgetattr(sys.stdin)
    f = open('record.txt', 'ab+')         # test

    try:
        tty.setraw(sys.stdin.fileno())
        tty.setcbreak(sys.stdin.fileno())
        chan.settimeout(0.0)
        cmd = ''
        records = []     # test

        tab_input_flag = False
        while True:
            r, w, e = select.select([chan, sys.stdin], [], [])

            if chan in r:
                try:
                    x = u(chan.recv(1024))
                    if tab_input_flag:                #处理有tab 键的时候。这里处理的是，我输入tab键补全后, server 端返回给我的内容，拿到tab 后自动补全的内容。
                        if x.startswith('\r\n'):      #拿到补全后的-所有的内容,可以不用处理。
                            pass
                        else:

                            cmd += ''.join(x[:10])
                            tab_input_flag = False

                    if len(x) == 0:
                        sys.stdout.write('\r\n\033[32;1m*** Session Closed ***\033[0m\r\n')
                        self.flush_cmd_input('*** Session Closed ***', host_ins, 2)
                        break

                    sys.stdout.write(x)      # 写到缓冲区了
                    sys.stdout.flush()       # flush 下，然后在页面上显示出来。

                except socket.timeout:
                    pass
                except UnicodeDecodeError as e:
                    pass

            if sys.stdin in r:
                ''' 用户读到内容，就把内容写到数据库里面。 '''
                x = sys.stdin.read(1)    # 接收用户 【敲进去】的取到的字符。
                records.append(x)        # test alex s8 期视频.
                if len(x) == 0:
                    break

                if not x == '\r':    # 当没有换行。 \r换行 相当于回车 \n新行
                    cmd += x
                else:                # 当有换行[回车].说明这个命令敲击完成了
                    if len(cmd.strip()) > 0:
                        ######### Test
                        # c_time = time.strftime('%Y-%m-%d %H:%M:%S')
                        # cmd_1 = ''.join(records).replace('\r', '\n')
                        # log = '%s    %s' % (c_time, cmd_1)
                        # f.write(log)
                        # records = []
                        ##########
                        print('==cmd==',cmd)
                        self.flush_cmd_input(cmd, host_ins, 0)  # 积攒你敲过的命令，点击查看下吧。


                    if cmd in unsupport_cmd_list:               # unsupport_cmd_list = ['rz', 'sz']
                        x = "...Operation is not supported!\r\n"
                    cmd = ''

                # print(ord(x))    # 这个命令可以捕获到我们敲进去的命令是什么数字代表，比如我们敲击回车，捕获到的是13. 当判断13的话就不用写了，很巧妙。
                if x == '\t':      # 判断我们【敲进去】命令里面有'\tab' 补全键。
                    tab_input_flag = True

                chan.send(x)

                # f.close()
    finally:
        termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
        f.close()

# thanks to Mike Looijmans for this code
def windows_shell(chan):
    import threading

    sys.stdout.write("Line-buffered terminal emulation. Press F6 or ^Z to send EOF.\r\n\r\n")

    def writeall(sock):
        while True:
            data = sock.recv(256)
            if not data:
                sys.stdout.write('\r\n\033[32;1m*** Session closed ***\033[0m\r\n\r\n')
                sys.stdout.flush()
                break
            sys.stdout.write(data)
            sys.stdout.flush()

    writer = threading.Thread(target=writeall, args=(chan,))
    writer.start()

    try:
        while True:
            d = sys.stdin.read(1)
            if not d:
                break
            chan.send(d)
    except EOFError:
        # user hit ^Z or F6
        pass
